#include "stdafx.h"
#include "Smooth.h"

namespace MyGame {

Smooth::Smooth(void) {
    this->iterations = 1;
    this->neighbourhood = NEIGHBOURHOOD_MOORE;
}

Smooth::~Smooth(void) {
}

int Smooth::GetIterations() const {
    return this->iterations;
}

void Smooth::SetIterations(int val) {
    this->iterations = val;
}

Neighbourhood Smooth::GetNeighbourhood() const {
    return this->neighbourhood;
}

void Smooth::SetNeighbourhood(Neighbourhood val) {
    this->neighbourhood = val;
}

void Smooth::Generate(HeightMap* heightMap) {
    int width = heightMap->GetWidth();
    int length = heightMap->GetLength();
    FLOAT** map = heightMap->GetMap();
    int xNeighbours;
    int zNeighbours;
    int xShift;
    int zShift;
    int xIndex;
    int zIndex;

    for (int i = 0; i < this->iterations; ++i) {
        for (int z = 0; z < length; ++z) {
            if (z == 0) {
                zNeighbours = 2;
                zShift = 0;
                zIndex = 0;
            } else if (z == length - 1) {
                zNeighbours = 2;
                zShift = -1;
                zIndex = 1;
            } else {
                zNeighbours = 3;
                zShift = -1;
                zIndex = 1;
            }

            for (int x = 0; x < width; ++x) {
                if (x == 0) {
                    xNeighbours = 2;
                    xShift = 0;
                    xIndex = 0;
                } else if (x == width - 1) {
                    xNeighbours = 2;
                    xShift = -1;
                    xIndex = 1;
                } else {
                    xNeighbours = 3;
                    xShift = -1;
                    xIndex = 1;
                }

                FLOAT hCumulative = 0.0f;
                int nNeighbours = 0;
                for (int nz = 0; nz < zNeighbours; ++nz) {
                    for (int nx = 0; nx < xNeighbours; ++nx) {
                        if (this->neighbourhood == NEIGHBOURHOOD_MOORE ||
                                (this->neighbourhood == NEIGHBOURHOOD_VONNEUMANN && (nx == xIndex || nz == zIndex))) {
                            float heightAtPoint = map[x + nx + xShift][z + nz + zShift];
                            hCumulative += heightAtPoint;
                            nNeighbours++;
                        }
                    }
                }

                FLOAT hAverage = hCumulative / nNeighbours;
                map[x + xIndex + xShift][z + zIndex + zShift] = hAverage;
            }
        }
    }
}

}
